<template>
  <div class="media-viewer" :class="{ 'no-transition': disableTransition, swiping }" ref="viewer">
    <div
      v-for="item in renderItems"
      class="swipe-item"
      :class="{
        curr: currItem === item,
        prev: prevItem === item,
        next: nextItem === item,
        out: currItem !== item && prevItem !== item && nextItem !== item,
        out: currItem !== item && prevItem !== item && nextItem !== item,
      }"
      :key="item.id"
      :style="{
        transitionDuration: currItem === item || prevItem === item || nextItem === item ? transitionDuration : '',
        transform: swiping
          ? currItem === item
            ? currTranslateY
            : prevItem === item
            ? prevTranslateY
            : nextItem === item
            ? nextTranslateY
            : ''
          : '',
      }"
      @transitionend.self="currItem === item && resetTransitionDuration()"
    >
      <ViewerBanner
        v-if="isAd(item)"
        :item="item"
        :active="active && currItem === item"
        :ready="ready && (currItem === item || prevItem === item || nextItem === item)"
        @next="changeMedia(1, 'up', 1)"
      >
      </ViewerBanner>
      <Video
        v-else-if="showVideo(item)"
        :url="item.video_path"
        :active="active && currItem === item"
        :ready="ready && (currItem === item || prevItem === item || nextItem === item)"
        :stat-info="{ id: item.id, available: mediaAvailable(item) }"
        :watermark="[FEED_PERMISION.SUB, FEED_PERMISION.SHOP].includes(item.visible)"
        @play="handleVideoPlay"
        @pause="handleVideoPause"
        @seek="handleVideoSeek"
        @ended="handleVideoEnd"
        @update="handleVideoUpdate"
      >
      </Video>
      <PhotoSwiper
        v-else-if="showPhoto(item)"
        :item="item"
        :active="active && currItem === item"
        :ready="ready && (currItem === item || prevItem === item || nextItem === item)"
        :lock="showLockMask(item)"
        :fullscreen="photoFullscreen && currItem === item"
        :stat-info="{ id: item.id, available: mediaAvailable(item) }"
        :watermark="[FEED_PERMISION.SUB, FEED_PERMISION.SHOP].includes(item.visible)"
        @fullscreen="enterFullscreen(item)"
        @exit-fullscreen="photoFullscreen = false"
        @dbclick="featurePanelDbClick(item)"
      ></PhotoSwiper>
      <ErrorUnknown v-else></ErrorUnknown>
      <LockMask
        v-if="!isAd(item) && showLockMask(item)"
        :rights="item.need_rights"
        :is-block="item.author?.is_block"
        :is-subscribe="item.need_subscribe"
        :is-buy="item.need_buy"
        :buy-price="item.money"
      ></LockMask>
      <div
        v-if="!isAd(item)"
        class="feature-panel"
        :class="{ 'prevent-event': isFeaturePanelPreventEvent(item) }"
        v-show="!videoFullscreen"
      >
        <div class="info gap-col-8" :class="{ landscape: isLandscape }">
          <h2>
            <Link
              class="nickname font-size-16 font-weight-500 line-height-140"
              :href="`/${item.author.username}`"
              :title="item.author?.nickname"
              @click="$emit('click:avatar', item.aff)"
              >{{ item.author?.nickname }}</Link
            >
          </h2>
          <div
            v-if="!item.need_buy && !item.need_subscribe"
            class="watch-count font-size-12 font-weight-500 line-height-120"
          >
            <span class="count">{{ toKMBTString(item.click) }}</span>
            {{ $t('info.watches') }}
          </div>
          <div
            class="content font-size-14 font-weight-400 line-height-140"
            :class="{ fold: !contentExpandMap.get(item.id) }"
            @click.self="contentExpandMap.set(item.id, !contentExpandMap.get(item.id))"
          >
            {{ item.content }}
            <br />
            <Link
              v-for="tag in item.tags?.split(',').filter((t, i) => i !== 0 || t !== '')"
              class="tag font-weight-500"
              :key="tag"
              :href="`/tag/${tag}`"
              :title="tag"
              @click="$emit('click:tag', tag)"
              >#{{ tag }}</Link
            >
          </div>
        </div>
        <transition name="fold">
          <div v-show="isDesktop || isPortrait" class="btns gap-col-24" :style="featureBtnStyle">
            <div v-if="showVideo(item)" class="mute pointer">
              <Icon v-if="videoMuted" size="24" shadow @click="toggleVideoMuted" name="mute"></Icon>
              <Icon v-else size="24" shadow @click="toggleVideoMuted" name="unmute"></Icon>
              <Tip v-if="muteTipAutoShow" nowrap>{{ $t('common.muteTip') }}</Tip>
            </div>
            <div class="fullscreen pointer" @click="enterFullscreen(item)">
              <Icon v-if="isFullscreenIcon(item)" size="24" shadow name="fullscreen"></Icon>
              <Icon v-else size="24" shadow name="multiPhoto"></Icon>
            </div>
            <Link
              class="avatar"
              :href="`/${item.author.username}`"
              :title="item.author.nickname || item.author.username"
              @click="$emit('click:avatar', item.aff)"
            >
              <Avatar
                :src="item.author?.avatar"
                :radius="24"
                :vip="item.author.is_vip"
                border
                :vip-tier="item.author.tier"
              ></Avatar>
              <FollowPlusButton
                v-if="!item.author.is_follow && item.aff !== selfId"
                class="follow-plus"
                :user-id="item.aff"
                :feed-id="item.id"
              ></FollowPlusButton>
              <Tip v-if="subscribeTip && subscribeTip.aff === item.aff" heart-bubble>{{ subscribeTip.msg }}</Tip>
            </Link>
            <LikeButton
              class="like pointer"
              :id="item.id"
              :aff="item.author.aff"
              :is-like="item.liked"
              :like-count="item.like"
            ></LikeButton>
            <div class="chat pointer" @click="openChatPanel(item)">
              <Icon size="36" shadow name="chatBold"></Icon>
              <span class="font-size-12 font-weight-500">{{ toKMBTString(item.comment) }}</span>
            </div>
            <div class="share pointer" @click="shareLink(item)">
              <Icon size="36" shadow name="shareBold"></Icon>
            </div>
            <div v-if="item.aff !== selfId" class="donate pointer" @click="donate(item, 5 /*gtmKey*/, true)">
              <Icon size="36" shadow name="donateBold"></Icon>
            </div>
            <div v-if="item.aff !== selfId" class="more pointer" @click="more(item.aff, item.id)">
              <Icon size="36" name="more"></Icon>
            </div>
          </div>
        </transition>
        <VideoTimeBarController v-if="showVideo(item)" :active="active"></VideoTimeBarController>
      </div>
    </div>
    <ErrorNodata v-if="!loading && items.length === 0"></ErrorNodata>

    <!-- 雙擊點讚噴愛心 -->
    <FullOutHeart v-if="fullOutHeart" @end="fullOutHeart = false"></FullOutHeart>
  </div>
</template>

<script setup>
import {
  computed,
  onActivated,
  onBeforeUnmount,
  onDeactivated,
  onMounted,
  onUnmounted,
  reactive,
  ref,
  shallowRef,
  watch,
} from 'vue'
import { useEventListener, useLocalStorage } from '@vueuse/core'
import { storeToRefs } from 'pinia'
import { useAccountStore } from '@/store/account'
import { useAppStore } from '@/store/app'
import { useAuthDialogStore } from '@/store/auth-dialog'
import { useChatPanelStore } from '@/store/chat-panel'
import { useCreatorStore } from '@/store/creator'
import { useHeadStore } from '@/store/head'
import { usePopupMessageStore } from '@/store/popup-message'
import { useSubscribeTipStore } from '@/store/subscribe-tip'
import { $t, locale } from '@/i18n'
import { notifyLike } from '@/utils/state-broadcast'
import { toKMBTString } from '@/utils/string-helper'
import ViewerBanner from '@/components/banner/ViewerBanner.vue'
import ErrorNodata from '@/components/common/ErrorNodata.vue'
import ErrorUnknown from '@/components/common/ErrorUnknown.vue'
import Link from '@/components/common/Link.vue'
import Avatar from '@/components/multimedia/Avatar.vue'
import PhotoSwiper from '@/components/multimedia/PhotoSwiper.vue'
import Video from '@/components/multimedia/Video.vue'
import VideoTimeBarController from '@/components/viewer/VideoTimeBarController.vue'
import { useWheelWithoutSynthetic } from '@/compositions/desktop/wheelWithoutSynthetic'
import { useOnceOrDbClick } from '@/compositions/mobile/onceOrDbClick'
import { usePreventTouchmove } from '@/compositions/mobile/preventTouchmove'
import { useSwipe } from '@/compositions/mobile/swipe'
import { useCopyToClipboard } from '@/compositions/utils/copyToClipboard'
import { useDialog } from '@/compositions/viewer/dialog'
import { useVideoTimeBarStore } from '@/store/video-time-bar'
import {
  AD_TYPE,
  AUTH_ROUTES,
  FEED_PERMISION,
  FULLSCREEN_TYPE_THRESHOLD,
  LOCAL_STORAGE_KEYS,
  RIGHTS_TYPE,
} from '@/constant'
import { MEDIA_TYPE } from '@/constant/publish'
import { trackEvent } from '@/gtm'
import API from '@/http'
import LockMask from './LockMask.vue'
import FullOutHeart from './effect/FullOutHeart.vue'
import Tip from './effect/Tip.vue'
import FollowPlusButton from './stateful/FollowPlusButton.vue'
import LikeButton from './stateful/LikeButton.vue'

const { open: openMessage } = usePopupMessageStore()
const videoTimeBarStore = useVideoTimeBarStore()
const accountStore = useAccountStore()
const { isLogin, userId: selfId } = storeToRefs(accountStore)

const { donate, subscribe, shopBuy, more } = useDialog()

const { open: openAuthDialog } = useAuthDialogStore()

const chatPanelStore = useChatPanelStore()
const { isOpen: isChatPanelOpen } = storeToRefs(chatPanelStore)
const { open: openChatPanel, setFeed: updateChatPanel } = chatPanelStore

const props = defineProps({
  modelValue: { type: Number, required: true },
  items: { type: Array, required: true },
  active: { type: Boolean, required: true },
  ready: { type: Boolean, required: true },
  loading: { type: Boolean, default: false },
  disableTransition: { type: Boolean, default: false },
})
const emits = defineEmits(['update:modelValue', 'click:avatar', 'click:tag', 'toEnd'])

// 複製連結
const { copy } = useCopyToClipboard()
function shareLink(item) {
  API.Media.share({ data: { mv_id: item.id } }).catch((e) => {
    console.warn(e)
  })
  copy(item.share_url)

  trackEvent({ key: 4, meta: { id: item.id } })
}

// video 控制項
const appStore = useAppStore()

const { isDesktop, isPortrait, isLandscape, videoPlay, videoMuted, videoFullscreen } = storeToRefs(appStore)
const {
  toggleVideoPlay,
  toggleVideoFullscreen,
  toggleVideoMuted: $toggleVideoMuted,
  tickInstallTutorCounter,
} = appStore
const muteTipAutoShow = useLocalStorage(LOCAL_STORAGE_KEYS.MUTE_TIP_AUTO_SHOW, true)
function toggleVideoMuted() {
  $toggleVideoMuted()
  muteTipAutoShow.value = false
}

// 圖片全屏
const photoFullscreen = ref(false)

// 貼文內容折疊
const contentExpandMap = reactive(new Map())

// feature panel點擊一下就依據目前帖子狀態決定做啥事
const { getCreator } = useCreatorStore()
async function featurePanelClick(item) {
  // 強制註冊
  if (item.need_rights === RIGHTS_TYPE.REGISTER) {
    openAuthDialog(AUTH_ROUTES.SIGN_UP)
  }

  // 訂閱創作者
  else if (item.need_subscribe || item.need_rights === RIGHTS_TYPE.SUBSCRIBE) {
    const creator = await getCreator(item.author.aff)
    subscribe({
      item: {
        author: {
          aff: item.author.aff,
          avatar: item.author.avatar,
          nickname: item.author.nickname,
          username: item.author.username,
          price: creator.subscribe_price,
        },
        id: item.id,
      },
      gtmKey: 27,
    })
  }

  // 購買單筆帖子
  else if (item.need_buy) {
    shopBuy(item)
  }

  // 切換全域視頻播放switch
  else if (item.type === MEDIA_TYPE.VIDEO) {
    toggleVideoPlay()
    trackEvent({ key: videoPlay.value ? 7 : 8, meta: { id: item.id } })
  }
}

// 貼文點讚
const subscribeTipStore = useSubscribeTipStore()
const { subscribeTip } = storeToRefs(subscribeTipStore)
const { trigger, clear } = subscribeTipStore
const fullOutHeart = ref(false)
function featurePanelDbClick(item) {
  const toggler = item.liked ? API.Home.unlike : API.Home.like
  if (toggler === API.Home.like) {
    trackEvent({ key: 2, meta: { id: item.id } })
  }

  if (!isLogin.value) {
    openMessage($t('message.loginBeforeLike'))
    openAuthDialog()
    return
  }

  if (featurePanelDbClick.controller) {
    featurePanelDbClick.controller.abort()
  }
  featurePanelDbClick.controller = new AbortController()
  toggler({
    data: { mv_id: item.id },
    config: { signal: featurePanelDbClick.controller.signal },
  }).catch((e) => console.warn('Toggle feed like fail: ', e))

  fullOutHeart.value = !item.liked
  notifyLike(item.id, !item.liked)
  if (toggler === API.Home.like) {
    trigger(item.author.aff)
  } else {
    clear()
  }
}

// 各種用 item 中多種屬性來判別的顯示條件或操作
function isAd(item) {
  return item.type === AD_TYPE.VIDEO || item.type === AD_TYPE.PHOTO
}
function showVideo(item) {
  return item.type === MEDIA_TYPE.VIDEO && mediaAvailable(item)
}
function showPhoto(item) {
  return item.type === MEDIA_TYPE.IMAGE || !mediaAvailable(item)
}
function showLockMask(item) {
  return !mediaAvailable(item)
}
function isFeaturePanelPreventEvent(item) {
  return item.type === MEDIA_TYPE.IMAGE && mediaAvailable(item)
}
function enterFullscreen(item) {
  if (showVideo(item)) {
    toggleVideoFullscreen(true)
  }
  if (item.type === MEDIA_TYPE.IMAGE && mediaAvailable(item)) {
    photoFullscreen.value = true
  }
}
function mediaAvailable(item) {
  if (item.need_rights !== RIGHTS_TYPE.PASS) {
    return false
  }
  if (item.author?.is_block) {
    return false
  }
  if (item.need_subscribe || item.need_buy) {
    return false
  }
  return true
}
function isFullscreenIcon(item) {
  if (item.type === MEDIA_TYPE.VIDEO) {
    return true
  }
  if (item.type === MEDIA_TYPE.IMAGE) {
    if (!item.img_more) {
      return true
    }
    if (item.img_more.length < FULLSCREEN_TYPE_THRESHOLD) {
      return true
    }
  }
  return false
}

function changeMedia(dist, dir, delta, needTrack) {
  if (videoFullscreen.value) {
    return
  }

  // 關閉靜音提示
  muteTipAutoShow.value = false

  // pwa 安裝教學計數
  tickInstallTutorCounter()

  // 往下滑
  if (dir === 'down' && dist < 0 && delta < 0 && currIndex.value !== 0) {
    if (needTrack && !isAd(props.items[currIndex.value])) {
      trackEvent({ key: 11, meta: { id: props.items[currIndex.value].id } })
    }
    // handleVideoSwitch('down')
    currIndex.value -= 1
    if (currIndex.value - 1 >= props.items.length - 2) {
      emits('toEnd', { currentPlayTime: currentPlayTime.value })
    }
    return true
  }
  // 往上滑
  else if (dir === 'up' && dist > 0 && delta > 0 && currIndex.value < props.items.length - 1) {
    if (needTrack && !isAd(props.items[currIndex.value])) {
      trackEvent({ key: 11, meta: { id: props.items[currIndex.value].id } })
    }
    // handleVideoSwitch('up')
    currIndex.value += 1
    if (currIndex.value + 1 >= props.items.length - 2) {
      emits('toEnd', { currentPlayTime: currentPlayTime.value })
    }
    return true
  }
  return false
}

const viewer = ref(null)
const currIndex = computed({
  get: () => props.modelValue,
  set: (newPage) => emits('update:modelValue', newPage),
})
const currItem = computed(() => props.items[currIndex.value])
const prevItem = computed(() => props.items[currIndex.value - 1])
const nextItem = computed(() => props.items[currIndex.value + 1])

const currentPlayTime = ref(0)

const isPlaying = ref(false)
const seekThreshold = 1000 // 1秒阈值
let pauseReason = 'user' // 可能的取值: 'user', 'switch', 'end'

// 滑動操作
const { offset, swiping, transitionDuration, resetTransitionDuration } = useSwipe(viewer, {
  isVertical: true,
  isBlockBackward: () => currIndex.value === 0,
  isBlockForward: () => currIndex.value === props.items.length - 1,
  onBackward: () => changeMedia(-1, 'down', -1, true),
  onForward: () => changeMedia(1, 'up', 1, true),
  onReverseSwipe: (evt, direction) => {
    // 若此則為廣告要避免從左邊拉出創作者頁
    if (isAd(props.items[currIndex.value]) && direction === 'left') {
      evt.stopPropagation()
    }
  },
  onBackwardBlock: () => openMessage($t('boundary.start')),
  onForwardBlock: () => openMessage($t('boundary.end')),
})

// 阻止手機上下滑的時候會飄動
usePreventTouchmove(viewer)

// 滑動時的樣式
const currTranslateY = computed(() => {
  if (swiping.value) {
    return `translateY(${-offset.value}px)`
  }
  return ''
})
const prevTranslateY = computed(() => {
  if (swiping.value && offset.value < 0) {
    return `translateY(calc(-100% - ${offset.value}px))`
  }
  return ''
})
const nextTranslateY = computed(() => {
  if (swiping.value && offset.value > 0) {
    return `translateY(calc(100% - ${offset.value}px))`
  }
  return ''
})

// 真正要被渲染的 items
const renderItems = shallowRef([])
const prevRenderIndex = {}
function updateRenderItems([index, items, active], [, prevItems]) {
  const isSameItems = items === prevItems
  const { start: prevStart, end: prevEnd } = prevRenderIndex
  let start, end

  if (active) {
    const base = index % 10
    if (base < 9) {
      start = Math.max(0, index - base - 2)
      end = Math.min(items.length - 1, index + 10 - base)
    } else {
      start = index - 1
      end = Math.min(items.length - 1, start + 12)
    }
  } else {
    start = index
    end = index
  }
  if (isSameItems && start === prevStart && end === prevEnd) {
    return
  }

  prevRenderIndex.start = start
  prevRenderIndex.end = end
  const delay = (transitionDuration.value === null ? 0 : parseFloat(transitionDuration.value) * 1000) + 8
  setTimeout(() => {
    const itemsSlice = items.slice(start, end + 1)
    if (itemsSlice.length === 0) {
      delete prevRenderIndex.start
      delete prevRenderIndex.end
    } else {
      renderItems.value = itemsSlice
    }
  }, delay)
}
watch([currIndex, () => props.items, () => props.active], updateRenderItems, { immediate: true, deep: true })

watch(currIndex, (newValue, oldValue) => {
  if (newValue <= oldValue) {
    handleVideoSwitch('down')
  }
  if (newValue >= oldValue) {
    handleVideoSwitch('up')
  }
})

/* const currItem = computed(() => props.items[currIndex.value])
const prevItem = computed(() => props.items[currIndex.value - 1])
const nextItem = computed(() => props.items[currIndex.value + 1]) */

// 支援桌面版滑鼠滾輪
useWheelWithoutSynthetic(viewer, (evt) => {
  const dist = evt.deltaY
  const dir = dist > 0 ? 'up' : 'down'
  changeMedia(dist, dir, dist)
})

// feature-panel 點一下或兩下事件綁定
useOnceOrDbClick(
  viewer,
  // 一下
  () => featurePanelClick(props.items[currIndex.value]),
  // 兩下
  () => featurePanelDbClick(props.items[currIndex.value]),
  { triggerClassName: 'feature-panel' },
)

// 桌面版會發生切換帖子時留言面板開啟中，需要更新其內容
watch(currIndex, (v) => {
  if (isChatPanelOpen.value) {
    updateChatPanel(props.items[v])
  }
})

// 每次切換的時候就要把 url 和 head 顯示成對應的媒體訊息，OK，沒問題的！
const { toMediaHead } = useHeadStore()
watch(currIndex, (v) => {
  const item = props.items[v]
  if (!item || isAd(item)) return
  const type = item.type === MEDIA_TYPE.VIDEO ? 'video' : 'photo'
  const url = `/${locale.value}/${item.author.username}/${type}/${item.id}`
  window.history.replaceState({}, '', url)
  toMediaHead(item)
})

// 右側功能根據viewport高度縮放
const featureBtnStyle = ref({ transform: `scale(1)`, transformOrigin: 'center bottom' })
const SCALE_THRESHOLD = 777
function resizeFeatureBtns() {
  const viewportHeight = window.innerHeight
  if (viewportHeight < SCALE_THRESHOLD) {
    const scale = viewportHeight / SCALE_THRESHOLD
    featureBtnStyle.value.transform = `scale(${scale < 0.5 ? 0 : scale})`
  } else {
    featureBtnStyle.value.transform = `scale(1)`
  }
}
useEventListener('resize', resizeFeatureBtns)
resizeFeatureBtns()

// 修改后的视频事件处理函数
function handleVideoPlay(event) {
  if (!isPlaying.value) {
    isPlaying.value = true
    reportEvent({
      video_id: currItem.value.id,
      event: 'videoPlay',
      current_play_time: parseInt(event?.currentPlayTime * 1000),
      timestamp: Date.now(),
    })
  }
  
  pauseReason = 'user' 
}


function handleVideoPause(event) {
  if (isPlaying.value && pauseReason === 'user') {
    isPlaying.value = false
    reportEvent({
      video_id: currItem.value.id,
      event: 'videoPause',
      current_play_time: parseInt(currentPlayTime.value),
      timestamp: Date.now(),
    })
  }
  pauseReason = 'user' // 重置暂停原因
}

function handleVideoSeek(event) {
  const seekDiff = Math.abs(event.target_time - event.start_time);
  if (seekDiff > seekThreshold) {
    isPlaying.value = false
    reportEvent({
      event: 'videoSeek',
      video_id: currItem.value.id,
      ...event
    })
  }
}

function handleVideoEnd(event) {
  console.log('ended event');
  if (event.currentPlayTime > seekThreshold) {  // 忽略第一次自动播放完成回传的错误数据
    isPlaying.value = false
    pauseReason = 'end'
    reportEvent({
      event: 'videoEnd',
      video_id: currItem.value.id,
      current_play_time: parseInt(currentPlayTime.value),
      timestamp: Date.now(),
    })
  }
}

function handleVideoUpdate(event) {
  currentPlayTime.value = event.currentPlayTime * 1000
}

const reportList = ref({
  video_id: null,
  events: [],
  timestamp: 0,
})

// 修改视频切换处理函数
function handleVideoSwitch(dir) {
  // 标记暂停原因
  pauseReason = 'switch'
  
  // 记录切换事件
  reportEvent({
    event: 'videoSwitch',
    video_id: dir === 'down' ? nextItem.value.id : prevItem.value.id,
    next_video_id: currItem.value.id,
    current_play_time: parseInt(currentPlayTime.value),
    timestamp: Date.now(),
  })

  // 重置状态
  isPlaying.value = false
  pauseReason = 'user'

  // 立即发送事件
  flushPendingEvents(true)
  videoTimeBarStore.reset()
}

// 添加立即刷新事件的函数
function flushPendingEvents(force = false) {
  if (reportList.value.events.length === 0) return
  if (!currItem.value.id) return

  // 如果超过500ms或强制发送
  const now = Date.now()
  if (force || now - reportList.value.timestamp > 200) {
    API.Home.reportEvents({ data: reportList.value }).finally(() => {
      reportList.value.video_id = currItem.value.id
    })
  }
  reportList.value.events = []
}

// 修改 reportEvent 函数
function reportEvent(data) {
  // 过滤无效事件
  if (!data.video_id) return
  
  // // 合并连续的同类型事件（可根据需要扩展）
  // const lastEvent = reportList.value.events[reportList.value.events.length - 1]
  // if (lastEvent && lastEvent.event === data.event) {
  //   // 如果是播放事件，只保留第一个
  //   if (data.event === 'videoPlay') return
  //   // 如果是暂停事件，更新时间为最后一次
  //   if (data.event === 'videoPause') {
  //     lastEvent.timestamp = data.timestamp
  //     return
  //   }
  // }

  reportList.value.events.push(data)
  
  // 自动刷新事件（防抖处理）
  // flushPendingEvents()
}

function handlePageLeave(e) {
  reportEvent({
    event: 'pageLeave', // 切换影片事件，当用户切换到下一部影片时触发
    video_id: currItem.value.id, // 当前播放的影片 ID
    page_leave_type: 'close',
    current_play_time: parseInt(currentPlayTime.value).toFixed(0) * 1, // 当前播放时间点（毫秒）
    timestamp: Date.now(), // Unix 毫秒
  })
  API.Home.reportEvents({ data: reportList.value })
    .then(() => {
      reportList.value.events = []
      reportList.value.video_id = currItem.value.id
    })
    .catch((e) => {
      reportList.value.events = []
      reportList.value.video_id = currItem.value.id
      console.warn(e)
    })
}

onMounted(() => {
  window.addEventListener('beforeunload', handlePageLeave)
})

onBeforeUnmount(() => {
  window.removeEventListener('beforeunload', handlePageLeave)
})

onUnmounted(() => {
  handlePageLeave()
})

onActivated(() => {
  console.log('onActivated')
})

onDeactivated(() => {
  handlePageLeave()
})
</script>

<style lang="scss" scoped>
@keyframes shake {
  0% {
    transform: rotate(0deg);
  }

  22% {
    transform: scale(1.1) rotate(-10deg);
  }

  45% {
    transform: scale(1.1) rotate(-20deg);
  }

  90% {
    transform: scale(1.1) rotate(5deg);
  }

  100% {
    transform: scale(1.1) rotate(0deg);
  }
}

.fold-enter-active,
.fold-leave-active {
  transition: transform 0.3s ease-in;
}

.fold-enter-from,
.fold-leave-to {
  transform: translateX(4rem);
}

.media-viewer {
  width: 100%;
  height: 100%;
  position: relative;

  &.no-transition {
    .swipe-item {
      transition: none;
    }
  }

  &.swiping {
    .swipe-item {
      transition: none;

      &.curr,
      &.prev,
      &.next {
        will-change: transform;
      }
    }
  }

  .swipe-item {
    width: 100%;
    height: 100%;
    position: absolute;
    transition: transform 0.25s ease-out;
    display: flex;
    justify-content: center;
    align-items: center;

    &.prev {
      transform: translateY(-100%);
    }

    &.next {
      transform: translateY(100%);
    }

    &.out {
      display: none;
    }
  }

  .feature-panel {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    background: linear-gradient(
      to bottom,
      rgba(65, 65, 65, 0.46) 0%,
      rgba(65, 65, 65, 0) 18.3%,
      rgba(65, 65, 65, 0) 66.5%,
      rgba(65, 65, 65, 0.43) 100%
    );

    &.prevent-event {
      pointer-events: none;
    }

    .info {
      pointer-events: initial;
      width: calc(100% - 1rem - 5rem);
      position: absolute;
      left: 1rem;
      bottom: 6.125rem;

      &.landscape {
        bottom: 0.5rem;
      }

      .watch-count {
        .count {
          margin-right: 0.3125rem;
        }
      }

      .content {
        letter-spacing: 0.2px;

        &.fold {
          overflow: hidden;
          display: -webkit-box;
          -webkit-box-orient: vertical;
          -webkit-line-clamp: 3;
        }

        .tag {
          display: inline-block;
          margin-right: 0.375rem;
        }
      }
    }

    .btns {
      pointer-events: initial;
      width: 3rem;
      position: absolute;
      right: 1rem;
      bottom: 6.1875rem;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;

      .mute,
      .fullscreen {
        width: 1.5rem;
        height: 1.5rem;
      }

      .avatar {
        width: 3rem;
        height: 3.5625rem;

        .follow-plus {
          transform: translate(0.9375rem, -0.5625rem);
        }
      }

      .like,
      .chat,
      .share,
      .donate {
        text-align: center;
      }

      .like,
      .chat {
        width: 2.5rem;
        height: 3.5rem;
      }

      .share,
      .donate,
      .more {
        width: 2.25rem;
        height: 2.25rem;
      }
    }
  }
}

.desktop {
  .media-viewer {
    .feature-panel {
      .info {
        width: calc(100% - 1rem - 9rem);
        left: 3rem;
        bottom: 1.5rem;
      }

      .btns {
        right: 1.5rem;
        bottom: 1.5rem;

        .chat,
        .share,
        .donate {
          &:hover .icon {
            animation: shake 0.5s ease 0s 1 forwards;
            transform-origin: bottom;
          }
        }
      }
    }
  }
}
</style>
